{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "028b8a19",
   "metadata": {},
   "source": [
    "节点、边（链接）、节点特征、边特征、标签。\n",
    "\n",
    "边权重等等\n",
    "\n",
    "同构图、异构图等等。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "0d12a75d",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "文件 tbl_player.csv 下载完成，保存在 data/fifa21_dataset\n",
      "文件 tbl_player_skill.csv 下载完成，保存在 data/fifa21_dataset\n",
      "文件 tbl_team.csv 下载完成，保存在 data/fifa21_dataset\n"
     ]
    }
   ],
   "source": [
    "import os\n",
    "import requests\n",
    "\n",
    "# 文件URL\n",
    "file_urls = [\n",
    "    \"https://raw.githubusercontent.com/batuhan-demirci/fifa21_dataset/master/data/tbl_player.csv\",\n",
    "    \"https://raw.githubusercontent.com/batuhan-demirci/fifa21_dataset/master/data/tbl_player_skill.csv\",\n",
    "    \"https://raw.githubusercontent.com/batuhan-demirci/fifa21_dataset/master/data/tbl_team.csv\"\n",
    "]\n",
    "\n",
    "# 指定保存文件的路径\n",
    "save_path = \"data/fifa21_dataset\"\n",
    "\n",
    "# 确保保存路径存在，如果不存在则创建\n",
    "os.makedirs(save_path, exist_ok=True)\n",
    "\n",
    "# 下载并保存文件\n",
    "for url in file_urls:\n",
    "    filename = os.path.join(save_path, os.path.basename(url))\n",
    "    response = requests.get(url)\n",
    "    with open(filename, \"wb\") as f:\n",
    "        f.write(response.content)\n",
    "    print(f\"文件 {os.path.basename(url)} 下载完成，保存在 {save_path}\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "539dc68c",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Players:  18767\n"
     ]
    },
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>int_player_id</th>\n",
       "      <th>str_player_name</th>\n",
       "      <th>str_positions</th>\n",
       "      <th>int_overall_rating</th>\n",
       "      <th>int_team_id</th>\n",
       "      <th>int_long_passing</th>\n",
       "      <th>int_ball_control</th>\n",
       "      <th>int_dribbling</th>\n",
       "      <th>str_team_name</th>\n",
       "      <th>int_overall</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>1</td>\n",
       "      <td>Lionel Andrés Messi Cuccittini</td>\n",
       "      <td>RW, ST, CF</td>\n",
       "      <td>93</td>\n",
       "      <td>5.0</td>\n",
       "      <td>91</td>\n",
       "      <td>96</td>\n",
       "      <td>96</td>\n",
       "      <td>FC Barcelona</td>\n",
       "      <td>84</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>33</th>\n",
       "      <td>2</td>\n",
       "      <td>Cristiano Ronaldo dos Santos Aveiro</td>\n",
       "      <td>ST, LW</td>\n",
       "      <td>92</td>\n",
       "      <td>6.0</td>\n",
       "      <td>77</td>\n",
       "      <td>92</td>\n",
       "      <td>88</td>\n",
       "      <td>Juventus</td>\n",
       "      <td>83</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>57</th>\n",
       "      <td>3</td>\n",
       "      <td>Jan Oblak</td>\n",
       "      <td>GK</td>\n",
       "      <td>91</td>\n",
       "      <td>8.0</td>\n",
       "      <td>40</td>\n",
       "      <td>30</td>\n",
       "      <td>12</td>\n",
       "      <td>Atlético Madrid</td>\n",
       "      <td>83</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>121</th>\n",
       "      <td>5</td>\n",
       "      <td>Neymar da Silva Santos Júnior</td>\n",
       "      <td>LW, CAM</td>\n",
       "      <td>91</td>\n",
       "      <td>7.0</td>\n",
       "      <td>81</td>\n",
       "      <td>95</td>\n",
       "      <td>95</td>\n",
       "      <td>Paris Saint-Germain</td>\n",
       "      <td>83</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>89</th>\n",
       "      <td>4</td>\n",
       "      <td>Kevin De Bruyne</td>\n",
       "      <td>CAM, CM</td>\n",
       "      <td>91</td>\n",
       "      <td>2.0</td>\n",
       "      <td>93</td>\n",
       "      <td>92</td>\n",
       "      <td>88</td>\n",
       "      <td>Manchester City</td>\n",
       "      <td>85</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>152</th>\n",
       "      <td>6</td>\n",
       "      <td>Robert Lewandowski</td>\n",
       "      <td>ST</td>\n",
       "      <td>91</td>\n",
       "      <td>4.0</td>\n",
       "      <td>70</td>\n",
       "      <td>88</td>\n",
       "      <td>85</td>\n",
       "      <td>FC Bayern München</td>\n",
       "      <td>84</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>178</th>\n",
       "      <td>10</td>\n",
       "      <td>Sadio Mané</td>\n",
       "      <td>LW</td>\n",
       "      <td>90</td>\n",
       "      <td>1.0</td>\n",
       "      <td>71</td>\n",
       "      <td>89</td>\n",
       "      <td>91</td>\n",
       "      <td>Liverpool</td>\n",
       "      <td>85</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>12</td>\n",
       "      <td>Marc-André ter Stegen</td>\n",
       "      <td>GK</td>\n",
       "      <td>90</td>\n",
       "      <td>5.0</td>\n",
       "      <td>63</td>\n",
       "      <td>30</td>\n",
       "      <td>21</td>\n",
       "      <td>FC Barcelona</td>\n",
       "      <td>84</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>179</th>\n",
       "      <td>11</td>\n",
       "      <td>Virgil van Dijk</td>\n",
       "      <td>CB</td>\n",
       "      <td>90</td>\n",
       "      <td>1.0</td>\n",
       "      <td>86</td>\n",
       "      <td>77</td>\n",
       "      <td>70</td>\n",
       "      <td>Liverpool</td>\n",
       "      <td>85</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>177</th>\n",
       "      <td>9</td>\n",
       "      <td>Mohamed Salah Ghaly</td>\n",
       "      <td>RW</td>\n",
       "      <td>90</td>\n",
       "      <td>1.0</td>\n",
       "      <td>75</td>\n",
       "      <td>89</td>\n",
       "      <td>90</td>\n",
       "      <td>Liverpool</td>\n",
       "      <td>85</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "     int_player_id                      str_player_name str_positions  \\\n",
       "0                1       Lionel Andrés Messi Cuccittini    RW, ST, CF   \n",
       "33               2  Cristiano Ronaldo dos Santos Aveiro        ST, LW   \n",
       "57               3                            Jan Oblak            GK   \n",
       "121              5        Neymar da Silva Santos Júnior       LW, CAM   \n",
       "89               4                      Kevin De Bruyne       CAM, CM   \n",
       "152              6                   Robert Lewandowski            ST   \n",
       "178             10                           Sadio Mané            LW   \n",
       "1               12                Marc-André ter Stegen            GK   \n",
       "179             11                      Virgil van Dijk            CB   \n",
       "177              9                  Mohamed Salah Ghaly            RW   \n",
       "\n",
       "     int_overall_rating  int_team_id  int_long_passing  int_ball_control  \\\n",
       "0                    93          5.0                91                96   \n",
       "33                   92          6.0                77                92   \n",
       "57                   91          8.0                40                30   \n",
       "121                  91          7.0                81                95   \n",
       "89                   91          2.0                93                92   \n",
       "152                  91          4.0                70                88   \n",
       "178                  90          1.0                71                89   \n",
       "1                    90          5.0                63                30   \n",
       "179                  90          1.0                86                77   \n",
       "177                  90          1.0                75                89   \n",
       "\n",
       "     int_dribbling        str_team_name  int_overall  \n",
       "0               96         FC Barcelona           84  \n",
       "33              88             Juventus           83  \n",
       "57              12      Atlético Madrid           83  \n",
       "121             95  Paris Saint-Germain           83  \n",
       "89              88      Manchester City           85  \n",
       "152             85    FC Bayern München           84  \n",
       "178             91            Liverpool           85  \n",
       "1               21         FC Barcelona           84  \n",
       "179             70            Liverpool           85  \n",
       "177             90            Liverpool           85  "
      ]
     },
     "execution_count": 2,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import pandas as pd\n",
    "\n",
    "# 加载数据\n",
    "player_df = pd.read_csv(\"data/fifa21_dataset/tbl_player.csv\")\n",
    "skill_df = pd.read_csv(\"data/fifa21_dataset/tbl_player_skill.csv\")\n",
    "team_df = pd.read_csv(\"data/fifa21_dataset/tbl_team.csv\")\n",
    "\n",
    "# 提取子集\n",
    "player_df = player_df[[\"int_player_id\", \"str_player_name\", \"str_positions\", \"int_overall_rating\", \"int_team_id\"]]\n",
    "skill_df = skill_df[[\"int_player_id\", \"int_long_passing\", \"int_ball_control\", \"int_dribbling\"]]\n",
    "team_df = team_df[[\"int_team_id\", \"str_team_name\", \"int_overall\"]]\n",
    "\n",
    "# 合并数据\n",
    "player_df = player_df.merge(skill_df, on='int_player_id') # 以int_player_id列进行合并\n",
    "fifa_df = player_df.merge(team_df, on='int_team_id') # 以int_team_id列进行合并\n",
    "\n",
    "# 排序\n",
    "fifa_df = fifa_df.sort_values(by=\"int_overall_rating\", ascending=False) # 以int_overall_rating列降序\n",
    "print(\"Players: \", fifa_df.shape[0])\n",
    "\n",
    "fifa_df = fifa_df[0:10] # 取10个数据\n",
    "\n",
    "fifa_df.head(10)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "eab410ae",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "1"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 确保没有重复的节点\n",
    "max(fifa_df[\"int_player_id\"].value_counts())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "4a5175ba",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>int_long_passing</th>\n",
       "      <th>int_ball_control</th>\n",
       "      <th>int_dribbling</th>\n",
       "      <th>CAM</th>\n",
       "      <th>CB</th>\n",
       "      <th>GK</th>\n",
       "      <th>LW</th>\n",
       "      <th>RW</th>\n",
       "      <th>ST</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>91</td>\n",
       "      <td>96</td>\n",
       "      <td>96</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>1</td>\n",
       "      <td>0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>33</th>\n",
       "      <td>77</td>\n",
       "      <td>92</td>\n",
       "      <td>88</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>1</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>57</th>\n",
       "      <td>40</td>\n",
       "      <td>30</td>\n",
       "      <td>12</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>1</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>89</th>\n",
       "      <td>93</td>\n",
       "      <td>92</td>\n",
       "      <td>88</td>\n",
       "      <td>1</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>121</th>\n",
       "      <td>81</td>\n",
       "      <td>95</td>\n",
       "      <td>95</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>1</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "     int_long_passing  int_ball_control  int_dribbling  CAM  CB  GK  LW  RW  \\\n",
       "0                  91                96             96    0   0   0   0   1   \n",
       "33                 77                92             88    0   0   0   0   0   \n",
       "57                 40                30             12    0   0   1   0   0   \n",
       "89                 93                92             88    1   0   0   0   0   \n",
       "121                81                95             95    0   0   0   1   0   \n",
       "\n",
       "     ST  \n",
       "0     0  \n",
       "33    1  \n",
       "57    0  \n",
       "89    0  \n",
       "121   0  "
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 以int_player_id列升序\n",
    "sorted_df = fifa_df.sort_values(by=\"int_player_id\")\n",
    "\n",
    "# 挑选节点特征\n",
    "node_features = sorted_df[[\"str_positions\", \"int_long_passing\", \"int_ball_control\", \"int_dribbling\"]]\n",
    "\n",
    "# 转换非数字列\n",
    "pd.set_option('mode.chained_assignment', None)\n",
    "positions = node_features[\"str_positions\"].str.split(\",\", expand=True)\n",
    "node_features[\"first_position\"] = positions[0]\n",
    "\n",
    "# one-hot编码\n",
    "node_features = pd.concat([node_features, pd.get_dummies(node_features[\"first_position\"])], axis=1, join='inner')\n",
    "node_features.drop([\"str_positions\", \"first_position\"], axis=1, inplace=True)\n",
    "\n",
    "# 转换True和False为1和0\n",
    "node_features = node_features.astype(int)\n",
    "node_features.head()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "8617f342",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[91 96 96  0  0  0  0  1  0]\n",
      " [77 92 88  0  0  0  0  0  1]\n",
      " [40 30 12  0  0  1  0  0  0]\n",
      " [93 92 88  1  0  0  0  0  0]\n",
      " [81 95 95  0  0  0  1  0  0]\n",
      " [70 88 85  0  0  0  0  0  1]\n",
      " [75 89 90  0  0  0  0  1  0]\n",
      " [71 89 91  0  0  0  1  0  0]\n",
      " [86 77 70  0  1  0  0  0  0]\n",
      " [63 30 21  0  0  1  0  0  0]]\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "(10, 9)"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 转换成numpy数组\n",
    "x = node_features.to_numpy()\n",
    "print(x)\n",
    "x.shape # [num_nodes, num_features]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "fc2c1231",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>int_overall</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>84</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>33</th>\n",
       "      <td>83</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>57</th>\n",
       "      <td>83</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>89</th>\n",
       "      <td>85</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>121</th>\n",
       "      <td>83</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>152</th>\n",
       "      <td>84</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>177</th>\n",
       "      <td>85</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>178</th>\n",
       "      <td>85</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>179</th>\n",
       "      <td>85</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>84</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "     int_overall\n",
       "0             84\n",
       "33            83\n",
       "57            83\n",
       "89            85\n",
       "121           83\n",
       "152           84\n",
       "177           85\n",
       "178           85\n",
       "179           85\n",
       "1             84"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 以int_player_id列定义顺序\n",
    "sorted_df = fifa_df.sort_values(by=\"int_player_id\")\n",
    "\n",
    "# 挑选标签列\n",
    "labels = sorted_df[[\"int_overall\"]]\n",
    "labels.head(10)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "03754f22",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[84]\n",
      " [83]\n",
      " [83]\n",
      " [85]\n",
      " [83]\n",
      " [84]\n",
      " [85]\n",
      " [85]\n",
      " [85]\n",
      " [84]]\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "(10, 1)"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 转换成numpy数组\n",
    "y = labels.to_numpy()\n",
    "print(y)\n",
    "y.shape # [num_nodes, 1]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "dc708b9f",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>int_player_id</th>\n",
       "      <th>str_player_name</th>\n",
       "      <th>str_positions</th>\n",
       "      <th>int_overall_rating</th>\n",
       "      <th>int_team_id</th>\n",
       "      <th>int_long_passing</th>\n",
       "      <th>int_ball_control</th>\n",
       "      <th>int_dribbling</th>\n",
       "      <th>str_team_name</th>\n",
       "      <th>int_overall</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>1</td>\n",
       "      <td>Lionel Andrés Messi Cuccittini</td>\n",
       "      <td>RW, ST, CF</td>\n",
       "      <td>93</td>\n",
       "      <td>5.0</td>\n",
       "      <td>91</td>\n",
       "      <td>96</td>\n",
       "      <td>96</td>\n",
       "      <td>FC Barcelona</td>\n",
       "      <td>84</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>33</th>\n",
       "      <td>2</td>\n",
       "      <td>Cristiano Ronaldo dos Santos Aveiro</td>\n",
       "      <td>ST, LW</td>\n",
       "      <td>92</td>\n",
       "      <td>6.0</td>\n",
       "      <td>77</td>\n",
       "      <td>92</td>\n",
       "      <td>88</td>\n",
       "      <td>Juventus</td>\n",
       "      <td>83</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>57</th>\n",
       "      <td>3</td>\n",
       "      <td>Jan Oblak</td>\n",
       "      <td>GK</td>\n",
       "      <td>91</td>\n",
       "      <td>8.0</td>\n",
       "      <td>40</td>\n",
       "      <td>30</td>\n",
       "      <td>12</td>\n",
       "      <td>Atlético Madrid</td>\n",
       "      <td>83</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>121</th>\n",
       "      <td>5</td>\n",
       "      <td>Neymar da Silva Santos Júnior</td>\n",
       "      <td>LW, CAM</td>\n",
       "      <td>91</td>\n",
       "      <td>7.0</td>\n",
       "      <td>81</td>\n",
       "      <td>95</td>\n",
       "      <td>95</td>\n",
       "      <td>Paris Saint-Germain</td>\n",
       "      <td>83</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>89</th>\n",
       "      <td>4</td>\n",
       "      <td>Kevin De Bruyne</td>\n",
       "      <td>CAM, CM</td>\n",
       "      <td>91</td>\n",
       "      <td>2.0</td>\n",
       "      <td>93</td>\n",
       "      <td>92</td>\n",
       "      <td>88</td>\n",
       "      <td>Manchester City</td>\n",
       "      <td>85</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>152</th>\n",
       "      <td>6</td>\n",
       "      <td>Robert Lewandowski</td>\n",
       "      <td>ST</td>\n",
       "      <td>91</td>\n",
       "      <td>4.0</td>\n",
       "      <td>70</td>\n",
       "      <td>88</td>\n",
       "      <td>85</td>\n",
       "      <td>FC Bayern München</td>\n",
       "      <td>84</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>178</th>\n",
       "      <td>10</td>\n",
       "      <td>Sadio Mané</td>\n",
       "      <td>LW</td>\n",
       "      <td>90</td>\n",
       "      <td>1.0</td>\n",
       "      <td>71</td>\n",
       "      <td>89</td>\n",
       "      <td>91</td>\n",
       "      <td>Liverpool</td>\n",
       "      <td>85</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>12</td>\n",
       "      <td>Marc-André ter Stegen</td>\n",
       "      <td>GK</td>\n",
       "      <td>90</td>\n",
       "      <td>5.0</td>\n",
       "      <td>63</td>\n",
       "      <td>30</td>\n",
       "      <td>21</td>\n",
       "      <td>FC Barcelona</td>\n",
       "      <td>84</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>179</th>\n",
       "      <td>11</td>\n",
       "      <td>Virgil van Dijk</td>\n",
       "      <td>CB</td>\n",
       "      <td>90</td>\n",
       "      <td>1.0</td>\n",
       "      <td>86</td>\n",
       "      <td>77</td>\n",
       "      <td>70</td>\n",
       "      <td>Liverpool</td>\n",
       "      <td>85</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>177</th>\n",
       "      <td>9</td>\n",
       "      <td>Mohamed Salah Ghaly</td>\n",
       "      <td>RW</td>\n",
       "      <td>90</td>\n",
       "      <td>1.0</td>\n",
       "      <td>75</td>\n",
       "      <td>89</td>\n",
       "      <td>90</td>\n",
       "      <td>Liverpool</td>\n",
       "      <td>85</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "     int_player_id                      str_player_name str_positions  \\\n",
       "0                1       Lionel Andrés Messi Cuccittini    RW, ST, CF   \n",
       "33               2  Cristiano Ronaldo dos Santos Aveiro        ST, LW   \n",
       "57               3                            Jan Oblak            GK   \n",
       "121              5        Neymar da Silva Santos Júnior       LW, CAM   \n",
       "89               4                      Kevin De Bruyne       CAM, CM   \n",
       "152              6                   Robert Lewandowski            ST   \n",
       "178             10                           Sadio Mané            LW   \n",
       "1               12                Marc-André ter Stegen            GK   \n",
       "179             11                      Virgil van Dijk            CB   \n",
       "177              9                  Mohamed Salah Ghaly            RW   \n",
       "\n",
       "     int_overall_rating  int_team_id  int_long_passing  int_ball_control  \\\n",
       "0                    93          5.0                91                96   \n",
       "33                   92          6.0                77                92   \n",
       "57                   91          8.0                40                30   \n",
       "121                  91          7.0                81                95   \n",
       "89                   91          2.0                93                92   \n",
       "152                  91          4.0                70                88   \n",
       "178                  90          1.0                71                89   \n",
       "1                    90          5.0                63                30   \n",
       "179                  90          1.0                86                77   \n",
       "177                  90          1.0                75                89   \n",
       "\n",
       "     int_dribbling        str_team_name  int_overall  \n",
       "0               96         FC Barcelona           84  \n",
       "33              88             Juventus           83  \n",
       "57              12      Atlético Madrid           83  \n",
       "121             95  Paris Saint-Germain           83  \n",
       "89              88      Manchester City           85  \n",
       "152             85    FC Bayern München           84  \n",
       "178             91            Liverpool           85  \n",
       "1               21         FC Barcelona           84  \n",
       "179             70            Liverpool           85  \n",
       "177             90            Liverpool           85  "
      ]
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "fifa_df.head(10)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "id": "1ca4e4af",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>int_player_id</th>\n",
       "      <th>str_player_name</th>\n",
       "      <th>str_positions</th>\n",
       "      <th>int_overall_rating</th>\n",
       "      <th>int_team_id</th>\n",
       "      <th>int_long_passing</th>\n",
       "      <th>int_ball_control</th>\n",
       "      <th>int_dribbling</th>\n",
       "      <th>str_team_name</th>\n",
       "      <th>int_overall</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>0</td>\n",
       "      <td>Lionel Andrés Messi Cuccittini</td>\n",
       "      <td>RW, ST, CF</td>\n",
       "      <td>93</td>\n",
       "      <td>5.0</td>\n",
       "      <td>91</td>\n",
       "      <td>96</td>\n",
       "      <td>96</td>\n",
       "      <td>FC Barcelona</td>\n",
       "      <td>84</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>33</th>\n",
       "      <td>1</td>\n",
       "      <td>Cristiano Ronaldo dos Santos Aveiro</td>\n",
       "      <td>ST, LW</td>\n",
       "      <td>92</td>\n",
       "      <td>6.0</td>\n",
       "      <td>77</td>\n",
       "      <td>92</td>\n",
       "      <td>88</td>\n",
       "      <td>Juventus</td>\n",
       "      <td>83</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>57</th>\n",
       "      <td>2</td>\n",
       "      <td>Jan Oblak</td>\n",
       "      <td>GK</td>\n",
       "      <td>91</td>\n",
       "      <td>8.0</td>\n",
       "      <td>40</td>\n",
       "      <td>30</td>\n",
       "      <td>12</td>\n",
       "      <td>Atlético Madrid</td>\n",
       "      <td>83</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>121</th>\n",
       "      <td>3</td>\n",
       "      <td>Neymar da Silva Santos Júnior</td>\n",
       "      <td>LW, CAM</td>\n",
       "      <td>91</td>\n",
       "      <td>7.0</td>\n",
       "      <td>81</td>\n",
       "      <td>95</td>\n",
       "      <td>95</td>\n",
       "      <td>Paris Saint-Germain</td>\n",
       "      <td>83</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>89</th>\n",
       "      <td>4</td>\n",
       "      <td>Kevin De Bruyne</td>\n",
       "      <td>CAM, CM</td>\n",
       "      <td>91</td>\n",
       "      <td>2.0</td>\n",
       "      <td>93</td>\n",
       "      <td>92</td>\n",
       "      <td>88</td>\n",
       "      <td>Manchester City</td>\n",
       "      <td>85</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>152</th>\n",
       "      <td>5</td>\n",
       "      <td>Robert Lewandowski</td>\n",
       "      <td>ST</td>\n",
       "      <td>91</td>\n",
       "      <td>4.0</td>\n",
       "      <td>70</td>\n",
       "      <td>88</td>\n",
       "      <td>85</td>\n",
       "      <td>FC Bayern München</td>\n",
       "      <td>84</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>178</th>\n",
       "      <td>6</td>\n",
       "      <td>Sadio Mané</td>\n",
       "      <td>LW</td>\n",
       "      <td>90</td>\n",
       "      <td>1.0</td>\n",
       "      <td>71</td>\n",
       "      <td>89</td>\n",
       "      <td>91</td>\n",
       "      <td>Liverpool</td>\n",
       "      <td>85</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>7</td>\n",
       "      <td>Marc-André ter Stegen</td>\n",
       "      <td>GK</td>\n",
       "      <td>90</td>\n",
       "      <td>5.0</td>\n",
       "      <td>63</td>\n",
       "      <td>30</td>\n",
       "      <td>21</td>\n",
       "      <td>FC Barcelona</td>\n",
       "      <td>84</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>179</th>\n",
       "      <td>8</td>\n",
       "      <td>Virgil van Dijk</td>\n",
       "      <td>CB</td>\n",
       "      <td>90</td>\n",
       "      <td>1.0</td>\n",
       "      <td>86</td>\n",
       "      <td>77</td>\n",
       "      <td>70</td>\n",
       "      <td>Liverpool</td>\n",
       "      <td>85</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>177</th>\n",
       "      <td>9</td>\n",
       "      <td>Mohamed Salah Ghaly</td>\n",
       "      <td>RW</td>\n",
       "      <td>90</td>\n",
       "      <td>1.0</td>\n",
       "      <td>75</td>\n",
       "      <td>89</td>\n",
       "      <td>90</td>\n",
       "      <td>Liverpool</td>\n",
       "      <td>85</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "     int_player_id                      str_player_name str_positions  \\\n",
       "0                0       Lionel Andrés Messi Cuccittini    RW, ST, CF   \n",
       "33               1  Cristiano Ronaldo dos Santos Aveiro        ST, LW   \n",
       "57               2                            Jan Oblak            GK   \n",
       "121              3        Neymar da Silva Santos Júnior       LW, CAM   \n",
       "89               4                      Kevin De Bruyne       CAM, CM   \n",
       "152              5                   Robert Lewandowski            ST   \n",
       "178              6                           Sadio Mané            LW   \n",
       "1                7                Marc-André ter Stegen            GK   \n",
       "179              8                      Virgil van Dijk            CB   \n",
       "177              9                  Mohamed Salah Ghaly            RW   \n",
       "\n",
       "     int_overall_rating  int_team_id  int_long_passing  int_ball_control  \\\n",
       "0                    93          5.0                91                96   \n",
       "33                   92          6.0                77                92   \n",
       "57                   91          8.0                40                30   \n",
       "121                  91          7.0                81                95   \n",
       "89                   91          2.0                93                92   \n",
       "152                  91          4.0                70                88   \n",
       "178                  90          1.0                71                89   \n",
       "1                    90          5.0                63                30   \n",
       "179                  90          1.0                86                77   \n",
       "177                  90          1.0                75                89   \n",
       "\n",
       "     int_dribbling        str_team_name  int_overall  \n",
       "0               96         FC Barcelona           84  \n",
       "33              88             Juventus           83  \n",
       "57              12      Atlético Madrid           83  \n",
       "121             95  Paris Saint-Germain           83  \n",
       "89              88      Manchester City           85  \n",
       "152             85    FC Bayern München           84  \n",
       "178             91            Liverpool           85  \n",
       "1               21         FC Barcelona           84  \n",
       "179             70            Liverpool           85  \n",
       "177             90            Liverpool           85  "
      ]
     },
     "execution_count": 13,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 重映射球员ID\n",
    "fifa_df[\"int_player_id\"] = fifa_df.reset_index().index\n",
    "fifa_df.head(10)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "3c254d60",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "str_team_name\n",
       "Liverpool              3\n",
       "FC Barcelona           2\n",
       "Juventus               1\n",
       "Atlético Madrid        1\n",
       "Paris Saint-Germain    1\n",
       "Manchester City        1\n",
       "FC Bayern München      1\n",
       "Name: count, dtype: int64"
      ]
     },
     "execution_count": 9,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 每支球队需要有多少球员\n",
    "fifa_df[\"str_team_name\"].value_counts()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "id": "b82bc8a2",
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[(0, 7)]\n",
      "[]\n",
      "[]\n",
      "[]\n",
      "[]\n",
      "[]\n",
      "[(6, 8), (6, 9), (8, 9)]\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "array([[0., 6., 6., 8.],\n",
       "       [7., 8., 9., 9.]])"
      ]
     },
     "execution_count": 10,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import itertools\n",
    "import numpy as np\n",
    "\n",
    "teams = fifa_df[\"str_team_name\"].unique()\n",
    "all_edges = np.array([], dtype=np.int32).reshape((0, 2)) # 链接存储\n",
    "\n",
    "for team in teams:\n",
    "    team_df = fifa_df[fifa_df[\"str_team_name\"] == team]\n",
    "    players = team_df[\"int_player_id\"].values # 获得需要连接的队员id\n",
    "\n",
    "    permutations = list(itertools.combinations(players, 2)) # 迭代的两两连接\n",
    "    print(permutations)\n",
    "\n",
    "    edges_source = [e[0] for e in permutations]\n",
    "    edges_target = [e[1] for e in permutations]\n",
    "    \n",
    "    team_edges = np.column_stack([edges_source, edges_target])\n",
    "    all_edges = np.vstack([all_edges, team_edges])\n",
    "    \n",
    "# 转换成Pytorch Geometric格式\n",
    "edge_index = all_edges.transpose()\n",
    "\n",
    "edge_index # [2, num_edges]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "id": "f83af918",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[0., 6., 6., 7., 8., 8., 9., 9.],\n",
       "       [7., 8., 9., 0., 6., 9., 6., 8.]])"
      ]
     },
     "execution_count": 11,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 复制数组中的列并颠倒它们的顺序\n",
    "edge_index  = np.concatenate([edge_index, edge_index[::-1]], axis=1)\n",
    "# 去除重复的边，确保每条边只出现一次\n",
    "edge_index  = np.unique(edge_index, axis=1)\n",
    "\n",
    "edge_index "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "id": "9859406e",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Data(x=[10, 9], edge_index=[2, 8], y=[10, 1])"
      ]
     },
     "execution_count": 12,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from torch_geometric.data import Data\n",
    "data = Data(x=x, edge_index=edge_index, y=y)\n",
    "\n",
    "# 有向图\n",
    "data"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "deep_learning",
   "language": "python",
   "name": "deep_learning"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.9.16"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
